//=============================================================================
//
// I2cTemp.cpp :
//
// This example shows how to sense the temperature with the I2C temperature
// sensor DS1631. After writing some initialisation bytes the program enters
// a loop updating the measured value for the temperature every 500ms.
//
//-----------------------------------------------------------------------------
// Disclaimer - Exclusion of Liability
//
// This software is distributed in the hope that it will be useful,but WITHOUT 
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
// FITNESS FOR A PARTICULAR PURPOSE. It can be used an modified by anyone
// free of any license obligations or authoring rights.
//=============================================================================

#include "StdAfx.h"

#define STRMAXLEN   80

HANDLE	fthdl;
DWORD	errCode;
char	ComPortName[STRMAXLEN];
char    LibVersion[STRMAXLEN];
char	ResultStr[STRMAXLEN];

#define INIT_1				 0
#define WAIT_1				 1
#define INIT_2				 2
#define WAIT_2				 3
#define INIT_3				 4
#define WAIT_3				 5
#define INIT_4				 6
#define WAIT_4				 7
#define LOOP_WRITE			 8
#define LOOP_WRITE_WAIT		 9
#define LOOP_READ			10
#define LOOP_READ_WAIT		11
#define LOOP_DISP_RESULT	12

int stage=0;
unsigned short value=0;
unsigned short status=0;

#define DEVADDR 0x4F        // I2C address of temperatur sensor DS1631

/*-----------------------------------------------------------------------------
 *  I2c Callback Routine  
 *---------------------------------------------------------------------------*/
void __stdcall cbI2c(I2C_CB * reply)
{
    value = reply->value;
	status = reply->status;

	stage++;
}

/*-----------------------------------------------------------------------------
 *  I2c Access Routines  
 *---------------------------------------------------------------------------*/
static DWORD I2cRead(BYTE devaddr, DWORD offset, BYTE protocol) 
{
	return(ftxI2cRead(fthdl, devaddr, offset, protocol, cbI2c));
}

static DWORD I2cWrite(BYTE devaddr, DWORD offset, WORD data, BYTE protocol) 
{
	return(ftxI2cWrite(fthdl, devaddr, offset, data, protocol, cbI2c));
}

/*-----------------------------------------------------------------------------
 *  DisplayResult  
 *---------------------------------------------------------------------------*/

static void DisplayResult(void)
{
	int fraction=0;
    unsigned char temp=0;
    char sign = ' ';

	switch(status)
	{
		case I2C_SUCCESS:
			if(value & 0x0080) fraction = 5;
			else fraction = 0; 
			if(value & 0x8000) 
			{
				sign = '-';
				temp = value >> 8;
				temp = ~temp;
			}    
			else 
			{
				sign = '+';
				temp = value >> 8;
			}    
		    sprintf(ResultStr, "\rTemperature: %c%d,%d C    ", sign, temp, fraction);
			break;

		case I2C_READ_ERROR:
			sprintf(ResultStr, "\rI2C_READ_ERROR                        ");
			break;
		
		case I2C_WRITE_ERROR:
			sprintf(ResultStr, "\rI2C_WRITE_ERROR                       ");
			break;
	}

    cout << ResultStr << flush;
}

/*-----------------------------------------------------------------------------
 *  RunThermometer  
 *---------------------------------------------------------------------------*/

static void RunThermometer(void)
{
	DWORD error=0;
	char str_error_stage[32];
	
	stage = INIT_1;

	while(!error && !kbhit())
	{
		switch(stage)
		{
			case INIT_1:
				cout << "Write INIT_1" << endl;
				if(error = I2cWrite(DEVADDR, 0xAC, 0x02, 0x85)) 
					strcpy(str_error_stage, "INIT_1");
				stage++;
				break;

			case INIT_2:
				cout << "Write INIT_2" << endl;
				if(error = I2cWrite(DEVADDR, 0xA1, 0x2800, 0x89))
					strcpy(str_error_stage, "INIT_2");
				stage++;
				break;
				
			case INIT_3:
				cout << "Write INIT_3" << endl;
				if(error = I2cWrite(DEVADDR, 0xA2, 0x0A00, 0x89))
					strcpy(str_error_stage, "INIT_3");
				stage++;
				break;

			case INIT_4:
				cout << "Write INIT_4" << endl;
				if(error = I2cWrite(DEVADDR, 0x00, 0x51, 0x84))
					strcpy(str_error_stage, "INIT_4");
				stage++;
				cout << "Start Loop...(terminate with any key)\n" << endl;
				break;

			case WAIT_1:  
			case WAIT_2:  
			case WAIT_3:  
			case WAIT_4:  
				// waiting for callback
				break;	
				
			case LOOP_WRITE:
				if(error = I2cWrite(DEVADDR, 0x00, 0xAA, 0x84))
					strcpy(str_error_stage, "LOOP_WRITE");
				stage++;
				break;;
                
			case LOOP_WRITE_WAIT:
				// waiting for callback    
				break;

			case LOOP_READ:
				if(error= I2cRead(DEVADDR, 0x00, 0x88))
					strcpy(str_error_stage, "LOOP_READ");
				stage++;
				break;;
                
			case LOOP_READ_WAIT:
				// waiting for callback    
				break;
                
			case LOOP_DISP_RESULT:
				DisplayResult();
				Sleep(500);
				stage = LOOP_WRITE;
				break;
		}
	}

	if(error)
	{
		char str_error_text[32];

		switch(error)
		{
			case 0xE0005000:
				strcpy(str_error_text, "FTLIB_I2C_INVALID_DEV_ADDR");
				break;
			case 0xE0005001:
				strcpy(str_error_text, "FTLIB_I2C_INVALID_FLAGS_ADDRMODE");
				break;
			case 0xE0005002:
				strcpy(str_error_text, "FTLIB_I2C_INVALID_FLAGS_DATAMODE");
				break;
			case 0xE0005003:
				strcpy(str_error_text, "FTLIB_I2C_INVALID_FLAGS_ERRMODE");
				break;
		}

		cout << "\nRunThermometer: error " << str_error_text << " occured in stage " << str_error_stage << endl << endl;
	}
	else
	{
		cout << "\n\nRunThermometer: User termination" << endl << endl;
	}
}
 
 /*-----------------------------------------------------------------------------
 *  CheckParameter  
 *---------------------------------------------------------------------------*/
static int ChckCOMPar(int argc, char* argv[]) {

    char    *pStr;
    int     comNo;

    if (argc >= 2) {
        if (strlen(argv[1]) > 3) {
            if ((pStr=strstr(argv[1],"COM")) != NULL) {
                sscanf(pStr+3, "%d", &comNo);
                if (comNo >= 1 && comNo <= 255)
                    return 0;
                else {
                    cout << "I2cTemp.exe: invalid COM number..." << endl << endl;
                    return 1;
                }
            }
        }
    }

    cout << "I2cTemp.exe: no input given..." << endl << endl;
    return 1;
}


/*-----------------------------------------------------------------------------
 *  main
 *---------------------------------------------------------------------------*/
int main(int argc, char* argv[]) {

    cout << "\nExample I2cTemp.exe ..." << endl;

    //  check input paramter
    if (ChckCOMPar(argc,argv)) {
        cout << "Usage: I2cTemp.exe COMxx\t(e.g. COM2 or COM32)" << endl;
        return 1;
    }

    //  get library version
    ftxGetLibVersionStr(LibVersion, STRMAXLEN);
    cout << "\nftMscLib " << LibVersion << endl; 
    
    //  library initialization
    errCode = ftxInitLib();

    strcpy(ComPortName, argv[1]);
    cout << "\n\nOpen ComPort '" << ComPortName << "' ..." << endl;

    //  open COM port
    fthdl = ftxOpenComDevice(ComPortName, 38400, &errCode);

    if ( errCode == FTLIB_ERR_SUCCESS ) {

        cout << "Connected to ROBO TX Controller ..." << endl;

        //  starting transferarea
        errCode = ftxStartTransferArea(fthdl);

        if ( errCode == FTLIB_ERR_SUCCESS) {

            cout << "TransferArea was started and runs..." << endl;

			RunThermometer();

            //  stop TransferArea
            ftxStopTransferArea(fthdl);
        }

        else {
            //  error case
            cout << "Error: TransferArea was not started !" << endl << endl;
        }

        //  closing port and library
        cout << "Closing ComPort '" << ComPortName << "' ..." << endl;
	    errCode = ftxCloseDevice(fthdl);
    }

    else {
        //  error case
        cout << "Error: No interface available (Port '" << ComPortName << "')" << endl;
    }

    //  close library
    ftxCloseLib();

    return 0;
}
